package org.ansel.tools.eza;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Base64;

/** EPMS系统的手机号码AES加密算法。
 * 环境：jdk1.8.0_191。低版本可能会报错。
 * 使用方法：打jar包。
 * 在命令行中运行java -cp mytools-0.0.1.jar org.ansel.tools.eza.AESGCMEncryption "13012349876"
 *
 */
public class AESGCMEncryption {
    private static final int GCM_TAG_LENGTH = 128; // 16 bytes
    private static final int GCM_IV_LENGTH = 12; // 96 bits
    private static final String keyBytes = "zWjOz6+dj2ySQLURAs8bL8XSswpoUwgGadJ8nzkEc8E=";

    public static void main(String[] args) throws Exception {
        // 原始数据
        String originalText = "Hello, World!";
        try {
            originalText = args[0];
        }catch (Exception ex){
            System.out.println("没有入参，加密默认原始明文。");
        }
        // 加密
        String encryptedText = enkey(originalText);
        System.out.println("加密后的数据: " + encryptedText);

        String sss = "/KVzs6606hYspMIRJ84aVCez48qiWVnb5Ldd+LGQDiqjqVxwMJxPVp0=";
        // 解密
        String decryptedText = outkey(encryptedText);
        System.out.println("解密后的数据: " + decryptedText);

    }

    public static String enkey(String content){
        SecretKey secretKey = new SecretKeySpec(Base64.getDecoder().decode(keyBytes), "AES");
        String pStr = null;
        try {
            pStr = encrypt(content, secretKey);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return pStr;
    }

    public static String outkey(String content){
        SecretKey secretKey = new SecretKeySpec(Base64.getDecoder().decode(keyBytes), "AES");
        String postStr = null;
        try {
            postStr = decrypt(content, secretKey);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return postStr;
    }

    public static String encrypt(String text, SecretKey secretKey) throws Exception {
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
        byte[] iv = new byte[GCM_IV_LENGTH];
        new SecureRandom().nextBytes(iv);
        GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH, iv);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, gcmParameterSpec);
        byte[] cipherText = cipher.doFinal(text.getBytes(StandardCharsets.UTF_8));
        byte[] encryptedBytes = new byte[iv.length + cipherText.length];
        System.arraycopy(iv, 0, encryptedBytes, 0, iv.length);
        System.arraycopy(cipherText, 0, encryptedBytes, iv.length, cipherText.length);
        return Base64.getEncoder().encodeToString(encryptedBytes);
    }

    public static String decrypt(String encryptedText, SecretKey secretKey) throws Exception {
        byte[] encryptedBytes = Base64.getDecoder().decode(encryptedText);
        byte[] iv = new byte[GCM_IV_LENGTH];
        byte[] cipherText = new byte[encryptedBytes.length - iv.length];
        System.arraycopy(encryptedBytes, 0, iv, 0, iv.length);
        System.arraycopy(encryptedBytes, iv.length, cipherText, 0, cipherText.length);
        Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
        GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH, iv);
        cipher.init(Cipher.DECRYPT_MODE, secretKey, gcmParameterSpec);
        byte[] originalText = cipher.doFinal(cipherText);
        return new String(originalText, StandardCharsets.UTF_8);
    }
}
